///////////////////////////////////////////////////////////////////////////////////////
////// Hash function for jam_string
///////////////////////////////////////////////////////////////////////////////////////
namespace jamhash{ 
	template<class T> class hash		
	{
	public:
		char you_must_define_hash_function[0];
	};

	template<> class hash<jam_string>
	{
	public:	
		inline size_t operator()(const jam_string &str) const
		{			
			size_t res=str.get_hash();
			if (!res)
			{
				res=calc_hash(str);
				str.set_hash(res);
			}
			return res;
		}

		inline size_t calc_hash(const jam_string &str) const
		{
			size_t _Size = str.size();
			const char *data=str.data();
#ifdef BOOST_MSVC //TODO: need better condition
#define JAM_UINT16 unsigned short int
#define JAM_UINT32 unsigned int
			switch(_Size)
			{
			case 0:
				return 0xDEADBEEF;
			case 1:
				return str[0];
			case 2:
				return *(const JAM_UINT16*)(data);
			case 3:
				return *(const JAM_UINT16*)(data)+(((const JAM_UINT32)data[3])<<16);
			case 4:
				return *(const JAM_UINT32*)(data);
			default:
				;
			}
#endif
			// hash NTBS to size_t value
			size_t _Val = 0xDEADBEEF;
			if (0 < _Size)
			{
				// add one or more elements
				size_t _Stride = (_Size / 16) + 1;
				_Size -= _Stride;	// protect against _Size near str.max_size()
				for(size_t _Idx = 0; _Idx <= _Size; _Idx += _Stride)
					_Val += (size_t)data[_Idx];
			}
			return _Val;
		}
	};

}; //namespace jamhash
